package com.block.datapush.service.apipush.utils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * 80 有信 加密
 */
public class YouXinAesUtils {
    /**
     * 随机生成一个aesKey
     *
     * @return SecretKey
     * @throws Exception
     */
    public static String generateAESKey() throws Exception {
        KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
        keyGenerator.init(128);
        return Base64.getEncoder().encodeToString(keyGenerator.generateKey().getEncoded());
    }
    /**
     * 使用AES密钥加密传输数据
     *
     * @param jsonData json数据
     * @param aesKey   临时密钥
     * @return String
     * @throws Exception
     */
    public static String encryptData(String jsonData, String aesKey) throws Exception {
        SecretKeySpec key = new SecretKeySpec(Base64.getDecoder().decode(aesKey), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] encryptedJson = cipher.doFinal(jsonData.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encryptedJson);
    }
    /**
     * 使用RSA公钥加密随机AES密钥
     *
     * @param publicRSAKey RSA公钥
     * @return String
     * @throws Exception
     */
    public static String encryptKey(String publicRSAKey, String aesKey) throws Exception {
        byte[] publicKeyData = Base64.getDecoder().decode(publicRSAKey);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyData));
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedKey = cipher.doFinal(Base64.getDecoder().decode(aesKey));
        return Base64.getEncoder().encodeToString(encryptedKey);
    }

    /**
     * 解密aesKey原文
     *
     * @param encryptedKey 加密的aesKey
     * @param privateRSAKey rsa私钥
     * @return String
     * @throws Exception
     */
    public static String decryptKey(String encryptedKey, String privateRSAKey) throws Exception {
        byte[] privateKeyData = Base64.getDecoder().decode(privateRSAKey);
        byte[] encryptedAESKey = Base64.getDecoder().decode(encryptedKey);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(privateKeyData));
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decryptedAESKey = cipher.doFinal(encryptedAESKey);
        return Base64.getEncoder().encodeToString(decryptedAESKey);
    }

    /**
     * 解密JSON数据
     *
     * @param encryptedData 加密JSON数据
     * @param encryptedKey  加密key
     * @param privateRSAKey 私钥
     * @return String
     * @throws Exception
     */
    public static String decryptData(String encryptedData, String encryptedKey, String privateRSAKey) throws Exception {
        byte[] encryptJsonData = Base64.getDecoder().decode(encryptedData);
        String aesKey = decryptKey(encryptedKey, privateRSAKey);
        SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.getDecoder().decode(aesKey), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        byte[] decryptedJson = cipher.doFinal(encryptJsonData);
        return new String(decryptedJson, StandardCharsets.UTF_8);
    }

    public void test() throws Exception {
        String rsaPrivateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDBmYNKnEdIUBpkWVF9ew7++JeUNfxhTFwK05T7q1PUpNwckseuKRjNsEDA6WxyZWE7eZhBDkASkrE+yPCIxNfZDDxmcUjuvPupYWetKZ7enfrWdNNHP3mTOmqVDIzc0QKsGiO/CsvroPEZyYcQS0XewHjN/Sn2+PR9FaE8IkwBWGaLPsCvWuPeX97fNNe8Z3lfW16Wig/+2Hvz+K/fGotmI0Tq1E7uIdWb/4tfLMG5q7nu/0m29wdsF+jgnGLMBJ2JyUY1oYm+XyaM/pVeRRrqxydC6MX0VG5qAeNpuPlcGavynCVrPWi3+HyiciEg3CL9s/gRdxI+WoHcWcPj787lAgMBAAECggEATd2nj7+xb+U/6DKAcx6mlmh31tWrz5p9vqEA4AQ1sGYqXZevll3TKw+Dy9NWmeAqrlgmo6vOm2nCvkTlcazyP8sLFAzmT5dVBPg3Uc9WpaUWuWC9hX+DL3MkYRRuJ3YtQ/kzfWgjQn812bBTkXsk/AWf0QHM+heBhjnH4r7MoREv/142cbGKBqwrsEjS7Eem0Cr4FgicwLLctn3V+31lEKyUjbTTnJsIc3Kmip+fIESEGufIOC0ESr7PADbB0c1kLtM+5UtRtRXafi3P6Wv+3ERlp7tQRGxqPNdw2lA3yd4lFxv/oiTa4/raDdLnaBKzueL+rtMBbjQs1Kyd9XsTQQKBgQD3eY9gBmy22nXyVrxmkxvZB5fzUeU9z8zsXGTVGEQWJgUwUxp+8maz+UzN5EJdtydldawUV7qEViyqkqlGXf9HjpvB3dZV0cP9DSPLDoiOdMBpDO70VbheDqju7RJ5lZYOXVeobt1ejGf8LKqQCWX+oUKKZ9oNGzwTkrgRYS3xtQKBgQDIRNYe63835oNy1i5sqeMatOxpP31ac1gUAzOBpWLAwFRqy0iOnfRxENT3LUGla+zgaSpPUDWkHl4PzY8EsCXt/fr85Lar6ahsU+eXApg2kKn75A4UA4Lfxk83gKGzTAu4fiHva+xNBRP+MgnUceimKqvoqGIJSrp71l/VbzJmcQKBgQCrWTallS022kIqPlYKa7cvaSuTpNOmHbhUu5BxX3DdKQwUrqW82he0a1v7fx1YiBU2EejI2Qli0cvxesTL3Q+BO0OrUu8x0qDyGGP9F54DjOEgm3zkHmoebeYYMHvHRYR1g7nK/KA3892X5FFgk7FUQdGxxUBcLMxG/SKHnhLStQKBgQC17MJOCEPi9gYG9cXqdFGX2y6/VSt8VTd3xoithx20V4LYGJ5q39ZEN7QebgAqU2Y1XZNPxV9VHTj5RhRbf+CU15l+zg2bEYEsFvRUW8kGGFgyODMJvz7OJQmlM7awd65WBE6zfeiE9s34pmADmw5qlGzhxsR4CGhrQoyACKlSIQKBgQDU/WU/q9QYpmRX4Ln9rzE9CpgNnzV0WRWrybu5XnIAvky8a3SvL6bVkwDbBl7Wludx0mHa8WAqMJh1gmTDI5KTO3yEm6usoWjYY9fpYuK/+eSme1tqN55LraEK1ef6j9b+bBSJPmqEDC2gl5ZRg3n0J8Djcni8A6eCQ5w3nBZL5g==";
        String rsaPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwZmDSpxHSFAaZFlRfXsO/viXlDX8YUxcCtOU+6tT1KTcHJLHrikYzbBAwOlscmVhO3mYQQ5AEpKxPsjwiMTX2Qw8ZnFI7rz7qWFnrSme3p361nTTRz95kzpqlQyM3NECrBojvwrL66DxGcmHEEtF3sB4zf0p9vj0fRWhPCJMAVhmiz7Ar1rj3l/e3zTXvGd5X1telooP/th78/iv3xqLZiNE6tRO7iHVm/+LXyzBuau57v9JtvcHbBfo4JxizASdiclGNaGJvl8mjP6VXkUa6scnQujF9FRuagHjabj5XBmr8pwlaz1ot/h8onIhINwi/bP4EXcSPlqB3FnD4+/O5QIDAQAB";
        //请求方公钥加密
        String aesKey = YouXinAesUtils.generateAESKey();
        System.out.println("生成随机密钥成功！原文：" + aesKey);
        String encryptedData = YouXinAesUtils.encryptData("", aesKey);
        System.out.println("数据加密成功！密文：" + encryptedData);
        String encryptAesKey = YouXinAesUtils.encryptKey(rsaPublicKey, aesKey);
        System.out.println("密钥加密成功！加密后为：" + encryptAesKey);
        //接收方私钥解密
        String decryptData = YouXinAesUtils.decryptData(encryptedData, encryptAesKey, rsaPrivateKey);
        System.out.println("数据解密成功！解密后为：" + decryptData);
    }

}
